﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Windows;
using Microsoft.Win32;

namespace FileRenamer
{
    public class RenamerViewModel
    {
        public ObservableCollection<string> ChangerTypes { get; set; }
        public ObservableCollection<FileData> Files { get; set; }

        #region Button Commands
        private ICommand _addFilesCommand;
        public ICommand AddFilesCommand
        {
            get { return _addFilesCommand; }
            set { _addFilesCommand = value; }
        }

        private ICommand _removeFileCommand;
        public ICommand RemoveFileCommand
        {
            get { return _removeFileCommand; }
            set { _removeFileCommand = value; }
        }

        private ICommand _clearFilesCommand;
        public ICommand ClearFilesCommand
        {
            get { return _clearFilesCommand; }
            set { _clearFilesCommand = value; }
        }

        private ICommand _renameFilesCommand;
        public ICommand RenameFilesCommand
        {
            get { return _renameFilesCommand; }
            set { _renameFilesCommand = value; }
        }
        #endregion Button Commands

        public RenamerViewModel()
        {
            Files = new ObservableCollection<FileData>();
            ChangerTypes = new ObservableCollection<string>()
            {
                "Replace First Occurance With", 
                "Replace Last Occurance With", 
                "Replace All Occurances With", 
                "Append", 
                "Prepend", 
                "Sequence"
            };

            AddFilesCommand = new RelayCommand(new Action<object>(AddFiles));
            RemoveFileCommand = new RelayCommand(new Action<object>(RemoveFile));
            ClearFilesCommand = new RelayCommand(new Action<object>(ClearFiles));
            RenameFilesCommand = new RelayCommand(new Action<object>(RenameFiles));
        }


        string _cleanText = "";
        string _originalText = "";
        public string OriginalText
        {
            get { return _originalText; }
            set
            {
                _originalText = value;
                _cleanText = CleanInput(value);
                OnPropertyChanged("OriginalText");
                ChangeText();
            }
        }

        string _newText = "";
        public string NewText
        {
            get { return _newText; }
            set
            {
                _newText = CleanInput(value);
                OnPropertyChanged("NewText");
                ChangeText();
            }
        }

        bool _ignoreCase;
        public bool IgnoreCase
        {
            get { return _ignoreCase; }
            set
            {
                _ignoreCase = value;
                OnPropertyChanged("IgnoreCase");
                ChangeText();
            }
        }

        bool _ignoreExtension;
        public bool IgnoreExtension
        {
            get { return _ignoreExtension; }
            set
            {
                _ignoreExtension = value;
                OnPropertyChanged("IgnoreExtension");
                ChangeText();
            }
        }
        
        string _currentChangerType;
        public string CurrentChangerType
        {
            get { return _currentChangerType; }
            set
            {
                _currentChangerType = value;
                OnPropertyChanged("CurrentChangerType");
                ChangeText();
            }
        }
        
        int _seqStartingDigit = 0;
        public int SeqStartingDigit
        {
            get { return _seqStartingDigit; }
            set
            {
                _seqStartingDigit = value;
                OnPropertyChanged("SeqStartingDigit");
                ChangeText();
            }
        }

        int _seqLeadingZeros = 0;
        public int SeqLeadingZeros
        {
            get { return _seqLeadingZeros; }
            set
            {
                _seqLeadingZeros = value;
                OnPropertyChanged("SeqLeadingZeros");
                ChangeText();
            }
        }

        int _selectedFile = 0;
        public int SelectedFile
        {
            get { return _selectedFile; }
            set
            {
                _selectedFile = value;
                OnPropertyChanged("SelectedFile");
            }
        }

        static string CleanInput(string strIn)
        {
            try
            {
                return Regex.Escape(strIn);
            }
            catch
            {
                return String.Empty;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        private void cmdUp_Click(object sender, RoutedEventArgs e)
        {
            SeqLeadingZeros++;
        }

        private void cmdDown_Click(object sender, RoutedEventArgs e)
        {
            if(SeqLeadingZeros > 0) SeqLeadingZeros--;
        }

        private void ChangeText()
        {
            if (CurrentChangerType == ChangerTypes[0])
            {
                ReplaceFirstOccurance();
            }
            else if (CurrentChangerType == ChangerTypes[1])
            {
                ReplaceLastOccurance();
            }
            else if (CurrentChangerType == ChangerTypes[2])
            {
                ReplaceAllOccurances();
            }
            else if (CurrentChangerType == ChangerTypes[3])
            {
                AppendFileNames();
            }
            else if (CurrentChangerType == ChangerTypes[4])
            {
                PrependFileNames();
            }
            else if (CurrentChangerType == ChangerTypes[5])
            {
                SequenceFileNames();
            }
            
        }

        private void ReplaceFirstOccurance()
        {
            foreach (FileData fd in Files)
            {
                if (IgnoreCase)
                {
                    var regex = new Regex(Regex.Escape(_cleanText), RegexOptions.IgnoreCase);
                    fd.NewFileName = regex.Replace(fd.FileName, NewText, 1);
                }
                else
                {
                    var regex = new Regex(Regex.Escape(_cleanText));
                    fd.NewFileName = regex.Replace(fd.FileName, NewText, 1);
                }
                
                if (IgnoreExtension)
                {
                    fd.NewFileName += fd.FileExt;
                }
            }
        }

        private void ReplaceLastOccurance()
        {
            foreach (FileData fd in Files)
            {
                if (IgnoreCase)
                {
                    var regex = new Regex(Regex.Escape(_cleanText), RegexOptions.RightToLeft | RegexOptions.IgnoreCase);
                    fd.NewFileName = regex.Replace(fd.FileName, NewText, 1);
                }
                else
                {
                    var regex = new Regex(Regex.Escape(_cleanText), RegexOptions.RightToLeft);
                    fd.NewFileName = regex.Replace(fd.FileName, NewText, 1);
                }
                
                if (IgnoreExtension)
                {
                    fd.NewFileName += fd.FileExt;
                }
            }
        }

        private void ReplaceAllOccurances()
        {
            foreach (FileData fd in Files)
            {
                if (IgnoreCase)
                {
                    fd.NewFileName = Regex.Replace(fd.FileName, _cleanText, NewText, RegexOptions.IgnoreCase);
                }
                else
                {
                    fd.NewFileName = Regex.Replace(fd.FileName, _cleanText, NewText);
                }

                if (IgnoreExtension)
                {
                    fd.NewFileName += fd.FileExt;
                }
            }
        }


        private void AddFiles(object obj)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Multiselect = true;
            dlg.ShowDialog();

            foreach(string fileName in dlg.FileNames){
                FileData fd = new FileData();
                fd.FilePath = System.IO.Path.GetDirectoryName(fileName) + @"\";
                fd.FileName = System.IO.Path.GetFileName(fileName);
                fd.FileExt = System.IO.Path.GetExtension(fileName);
                fd.NewFileName = fd.FileName;

                bool exists = false;
                foreach (FileData f in Files)
                {
                    if (f.FileName == fd.FileName && f.FilePath == fd.FilePath)
                    {
                        exists = true;
                    }
                }

                if (!exists) Files.Add(fd);
            }
        }

        private void RemoveFile(object obj)
        {
            if (SelectedFile >= 0 && SelectedFile < Files.Count)
            {
                Files.RemoveAt(SelectedFile);
            }
        }

        private void ClearFiles(object obj)
        {
            Files.Clear();
        }

        private void RenameFiles(object obj)
        {
            foreach (FileData fd in Files)
            {
                System.IO.File.Move(fd.FilePath + fd.FileName, fd.FilePath + fd.NewFileName);
                fd.FileName = fd.NewFileName;
            }

            MessageBox.Show("Rename complete");
        }

        private void AppendFileNames()
        {
            foreach (FileData fd in Files)
            {
                if (!_ignoreExtension)
                {
                    fd.NewFileName = System.IO.Path.GetFileNameWithoutExtension(fd.FileName) + _cleanText + fd.FileExt;
                }
                else
                {
                    fd.NewFileName = fd.FileName + _cleanText;
                }
            }
        }

        private void PrependFileNames()
        {
            foreach (FileData fd in Files)
            {
                fd.NewFileName = _cleanText + fd.FileName;
            }
        }

        private void SequenceFileNames()
        {
            for (int i = 0; i < Files.Count; i++)
            {
                Files[i].NewFileName = (i + _seqStartingDigit).ToString().PadLeft(_seqLeadingZeros, '0');
                if (_ignoreExtension)
                {
                    Files[i].NewFileName += Files[i].FileExt;
                }
            }
        }
    }
}
